package com.wanxin.matcher;

import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;

@Component
public class RetyLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    /**
     * 声明缓存对象
     */
    private Ehcache passwordRetryEhcache;

    public RetyLimitHashedCredentialsMatcher(EhCacheManager ehcCacheManager) {
        passwordRetryEhcache = ehcCacheManager.getCacheManager().getCache("passwordRetryEhcache");
    }

    /**
     * 复写父类的登入认证方法，该方法有shiro的Login方法在底层调用
     * @param token 用户信息
     * @param info  用户登入
     * @return 是否在规定登入次数内登入成功
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        // 声明变量记录错误次数
        int i = 0;

        // 1.获取用户的登入次数的缓存信息
        // 获取用户的身份信息(身份信息为缓存数据的键名)
        String username = token.getPrincipal().toString();
        // 获取缓存对象
        Element element = passwordRetryEhcache.get(username);
        // 2.判断是否有缓存数据
        if (element == null) {
            // 没有缓存登入的错误次数，则创建新的缓存
            Element ele = new Element(username, new AtomicInteger(0));
            passwordRetryEhcache.put(ele);
        } else {
            // 有缓存则直接递增
            AtomicInteger atomicInteger = (AtomicInteger) element.getObjectValue();
            i = atomicInteger.incrementAndGet();
        }
        // 3.判断i的值是否为4
        if (i >= 4) {
            throw new ExcessiveAttemptsException();
        }
        // 4.进行本次请求的登入
        boolean match = super.doCredentialsMatch(token, info);
        // 5.如果登入成功则将错误次数的缓存 删除
        if (match) {
            passwordRetryEhcache.remove(username);
        }
        return match;
    }
}
